#include <vector>
#include <packet_quer.h>
#include <algorithm>
#include <iostream>

using namespace std;


typedef vector <Packet> vpacket; 
#define INIT_SIZE 1000

PacketQuer *PacketQuer::_quer = 0;
int PacketQuer::_instances = -1;
Thread *PacketQuer::_thr = 0;

struct MarkUsed
{
    int mark;
    MarkUsed(int val = 0) : mark(val) 
    {
    }     
    
    void operator()(Packet& x) 
    {
        x._in_use = mark;
    }
};

PacketQuer::PacketQuer()
{
   Packet pkt;
   _packet_list = new  vpacket(INIT_SIZE, pkt);
}

bool PacketQuer::removeAllPacketsInQue()
{
    vpacket *pkts = static_cast <vpacket *>(_packet_list); 

    _thr->lock();
    MarkUsed mk(0); 
    
    for_each(pkts->begin(), pkts->end(), mk);
    _thr->unlock();

    return true;
}

void PacketQuer ::destroyInstance()
{
    std::cout << "I was called \n";
    if (_quer) {
        if (_instances > 0) {
            _instances--;
            if (_instances == 0) {
                vpacket *pkts = static_cast <vpacket *>(_packet_list); 
                delete pkts;
                _instances = -1;
                _quer = 0;
                delete _thr;
            }
        }
    }
}

PacketQuer& PacketQuer::getInstance(Thread *_threadobj)
{
    if (_quer == 0) {
        _quer = new PacketQuer;
        _instances = 1;
        _thr = _threadobj;
    } else {
        _instances++;
    }
    return *_quer;
}

PacketQuer& PacketQuer::getInstance()
{
    if (_quer == 0) {
        throw "Thread object is not supplied ";
    } else {
        _instances++;
    }
    return *_quer;
}

bool PacketQuer::removePacketFromQue(Packet& pkt)
{
     bool retval = false;
     _thr->lock();
     vpacket *pkts = static_cast <vpacket *>(_packet_list); 
     vpacket::iterator it = find(pkts->begin(), pkts->end(), pkt);
     if (it != pkts->end()){
         it->_in_use = 0;
         retval = true;
     }
     _thr->unlock();
    return retval;
}

Packet *PacketQuer::getPacket()
{
    vpacket *pkts = static_cast <vpacket *>(_packet_list); 
    Packet *retPacket = 0;
    unsigned int i;

    _thr->lock();
    for (i = 0; i < pkts->size(); i++) {    
        if ((*pkts)[i]._in_use){
            retPacket = &((*pkts)[i]);
            break;
        }   
    }

    _thr->unlock();
    return retPacket;
}

bool PacketQuer::addToQue(Packet& pkt)
{
    vpacket *pkts = static_cast <vpacket *>(_packet_list); 
    //Find the first free slot
    
    unsigned int  i;
    bool retval = false;
    static int added;
    
    added++;

    _thr->lock();
    for (i = 0; i < pkts->size(); i++) {    
        if ((*pkts)[i]._in_use == 0 ){
            (*pkts)[i] = pkt;
            (*pkts)[i]._in_use = 1;
            retval = true;
            break;
        }   
    }

    _thr->unlock();
    return retval;
}

